<template>
  <div v-loading="uiOptions.loading">
    <el-dialog
      v-model="uiOptions.dialogMetricVisible"
      title="Metric Server"
      width="50%"
      :close-on-click-modal="false"
      @close="onCancel"
    >
      <el-form
        ref="createForm"
        label-position="top"
        :model="createForm"
        style="margin-left: 20px"
      >
        <el-form-item
          :label="$t('business.dashboard.metric_server_install_help')"
        >
          <el-tree :data="data" :props="dataTreeProps" />
        </el-form-item>
        <el-form-item
          :label="$t('business.dashboard.image')"
          prop="image"
          :rules="createFormRule"
        >
          <el-input v-model="createForm.image" />
        </el-form-item>
      </el-form>
      <template v-slot:footer>
        <div class="dialog-footer">
          <el-button size="small" @click="onCancel">{{
            $t("commons.button.cancel")
          }}</el-button>
          <el-button
            :disabled="!uiOptions.hasPermission"
            size="small"
            @click="onSubmit"
            >{{ $t("commons.button.confirm") }}</el-button
          >
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { checkPermissions } from "@/views/domain/kubeHud/utils/permission";
import { onMounted, reactive, ref } from "vue";
import { useInjectServer } from "./provider";
import { useK8SApi } from "@/views/domain/kubeHud/api/k8s";
import { ElMessage } from "element-plus";
import { useI18n } from "vue-i18n";
import { useFormRule } from "@/views/domain/kubeHud/utils/rules";

const { t } = useI18n();
/*
import { createService, listServices, updateService } from "@/api/services";
import {
  createClusterRole,
  listClusterRoles,
  updateClusterRole
} from "@/api/clusterroles";
import {
  createClusterRoleBinding,
  listClusterRoleBindings,
  updateClusterRoleBinding
} from "@/api/clusterrolebindings";
import {
  createRoleBinding,
  listRoleBindings,
  updateRoleBinding
} from "@/api/rolebings";
import {
  createServiceAccount,
  listServiceAccounts,
  updateServiceAccount
} from "@/api/serviceaccounts";
import { createWorkLoad, listWorkLoads, updateWorkLoad } from "@/api/workloads";
import { createApiServer, listApiServices, updateApiServer } from "@/api/apis";
*/
const { RequiredRule } = useFormRule();

const {
  serviceAccountRepo,
  roleBindingRepo,
  clusterRoleRepo,
  clusterRoleBindingRepo,
  serviceRepo,
  deploymentRepo
} = useK8SApi();

type Prop = {
  visible?: boolean;
  clusterName?: string;
};

const props = defineProps<Prop>();
const emit = defineEmits(["update:visible"]);

const uiOptions = reactive({
  loading: false, // loading
  dialogMetricVisible: false,
  hasPermission: false
});

const { genInjectMetricServer } = useInjectServer();

const data = ref<any[]>([]);
const dataTreeProps = { children: "children", label: "label" };

const serviceAccountList = ref<any[]>([]);
const roleBindingList = ref<any[]>([]);
const clusterRoleList = ref<any[]>([]);
const clusterRoleBindingList = ref<any[]>([]);
const serviceList = ref<any[]>([]);
const deploymentList = ref<any[]>([]);
const apiServiceList = ref<any[]>([]);

const createFormRef = ref();
const createForm = ref({
  image: ""
});
const createFormRule = {
  image: [RequiredRule]
};

const injectServiceItems = ref<any[]>(genInjectMetricServer());

const onSubmit = () => {
  uiOptions.loading = true;
  createFormRef.value.validate((valid: boolean) => {
    if (!valid) {
      return;
    }
    const ps = [];

    for (const item of injectServiceItems.value) {
      const lowerKind = item.kind.toLowerCase();
      switch (lowerKind) {
        case "serviceaccount":
          if (
            serviceAccountList.value.findIndex(
              item => item.metadata.name === item.metadata.name
            ) === -1
          ) {
            ps.push(
              serviceAccountRepo.createServiceAccount(
                props.clusterName,
                item.metadata.namespace,
                item
              )
            );
          } else {
            ps.push(
              serviceAccountRepo.updateServiceAccount(
                props.clusterName,
                item.metadata.namespace,
                item.metadata.name,
                item
              )
            );
          }
          break;
        case "rolebindings":
          if (
            roleBindingList.value.findIndex(
              item => item.metadata.name === item.metadata.name
            ) === -1
          ) {
            ps.push(
              roleBindingRepo.createRoleBinding(
                props.clusterName,
                item.metadata.namespace,
                item
              )
            );
          } else {
            ps.push(
              roleBindingRepo.updateRoleBinding(
                props.clusterName,
                item.metadata.namespace,
                item.metadata.name,
                item
              )
            );
          }
          break;
        case "clusterrole":
          if (
            clusterRoleList.value.findIndex(
              item => item.metadata.name === item.metadata.name
            ) === -1
          ) {
            ps.push(clusterRoleRepo.createClusterRole(props.clusterName, item));
          } else {
            ps.push(
              clusterRoleRepo.updateClusterRole(
                props.clusterName,
                item.metadata.name,
                item
              )
            );
          }
          break;
        case "clusterrolebinding":
          if (
            clusterRoleBindingList.value.findIndex(
              item => item.metadata.name === item.metadata.name
            ) === -1
          ) {
            ps.push(
              clusterRoleBindingRepo.createClusterRoleBinding(
                props.clusterName,
                item
              )
            );
          } else {
            ps.push(
              clusterRoleBindingRepo.updateClusterRoleBinding(
                props.clusterName,
                item.metadata.name,
                item
              )
            );
          }
          break;
        case "service":
          if (
            serviceList.value.findIndex(
              item => item.metadata.name === item.metadata.name
            ) === -1
          ) {
            ps.push(
              serviceRepo.createService({
                clusterName: props.clusterName,
                ...item
              })
            );
          } else {
            ps.push(
              serviceRepo.updateService({
                clusterName: props.clusterName,
                ...item
              })
            );
          }
          break;
        case "deployment":
          if (
            deploymentList.value.findIndex(
              item => item.metadata.name === item.metadata.name
            ) === -1
          ) {
            ps.push(
              deploymentRepo.createDeployment({
                clusterName: props.clusterName,
                ...item
              })
            );
          } else {
            ps.push(
              deploymentRepo.updateDeployment({
                clusterName: props.clusterName,
                ...item
              })
            );
          }
          break;
      }
    }

    Promise.all(ps)
      .then(() => {
        uiOptions.loading = false;
        uiOptions.dialogMetricVisible = false;
        ElMessage.success("success");
      })
      .catch(() => {
        uiOptions.loading = false;
      });
  });
};

const onCancel = () => {
  uiOptions.dialogMetricVisible = false;
  emit("update:visible", false);
};

const loadDatas = () => {
  serviceAccountRepo
    .listServiceAccounts(props.clusterName, "kube-system")
    .then(res => {
      serviceAccountList.value = res.items ?? [];
    });

  roleBindingRepo
    .listRoleBindings(props.clusterName, "kube-system")
    .then(res => {
      roleBindingList.value = res.items ?? [];
    });

  clusterRoleRepo.listClusterRoles(props.clusterName).then(res => {
    clusterRoleList.value = res.items ?? [];
  });

  clusterRoleBindingRepo
    .listClusterRoleBindings(props.clusterName)
    .then(res => {
      clusterRoleBindingList.value = res.items ?? [];
    });

  serviceRepo.getService({ cluster: props.clusterName }).then(res => {
    serviceList.value = res.items ?? [];
  });

  deploymentRepo
    .getDeploymentList({
      clusterName: props.clusterName,
      namespace: "kube-system"
    })
    .then(res => {
      deploymentList.value = res.items ?? [];
    });
};

const onYamlInit = async () => {
  for (const item of injectServiceItems.value) {
    const inDataItem = data.value.find(i => i.label === item.kind);
    if (inDataItem) {
      inDataItem.children.push({ label: item.metadata.name });
    } else {
      let hasPermission = false;
      switch (item.kind) {
        case "ServiceAccount":
          hasPermission = await checkPermissions({
            scope: "namespace",
            apiGroup: "",
            resource: "serviceaccounts",
            verb: "*"
          });
          break;
        case "RoleBinding":
          hasPermission = await checkPermissions({
            scope: "namespace",
            apiGroup: "rbac.authorization.k8s.io",
            resource: "rolebindings",
            verb: "*"
          });
          break;
        case "ClusterRole":
          hasPermission = await checkPermissions({
            scope: "cluster",
            apiGroup: "rbac.authorization.k8s.io",
            resource: "clusterroles",
            verb: "*"
          });
          break;
        case "ClusterRoleBinding":
          hasPermission = await checkPermissions({
            scope: "cluster",
            apiGroup: "rbac.authorization.k8s.io",
            resource: "clusterrolebindings",
            verb: "*"
          });
          break;
        case "Service":
          hasPermission = await checkPermissions({
            scope: "namespace",
            apiGroup: "",
            resource: "services",
            verb: "*"
          });
          break;
        case "Deployment":
          createForm.value.image = item.spec.template.spec.containers[0].image;
          hasPermission = await checkPermissions({
            scope: "namespace",
            apiGroup: "apps",
            resource: "deployments",
            verb: "*"
          });
          break;
        case "APIService":
          hasPermission = await checkPermissions({
            scope: "cluster",
            apiGroup: "apiregistration.k8s.io/v1",
            resource: "apiservices",
            verb: "*"
          });
          break;
      }
      data.value.push({
        label: item.kind,
        count: 1,
        hasPermission: hasPermission,
        children: [{ label: item.metadata.name }]
      });
    }

    data.value.forEach(item => {
      if (!item.hasPermission) {
        uiOptions.hasPermission = false;
      }

      item.label =
        `${item.label} [${item.count}]  ---` +
        (item.hasPermission
          ? t("business.dashboard.has_permission")
          : t("business.dashboard.has_not_permission"));
    });

    loadDatas();
  }
};

onMounted(() => {
  onYamlInit();
  uiOptions.dialogMetricVisible = true;
});
</script>
